﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Microsoft.Expression.Encoder.Devices;
using Microsoft.Expression.Encoder.Live;
using Microsoft.Expression.Encoder;
using System.IO;
using System.Timers;


namespace WebCamDVR
{
    public partial class frmDVR : Form
    {
        LiveJob job;
        LiveJob job1;
        LiveJob job2;
        LiveJob job3;
        EncoderDevice video;
        EncoderDevice audio;
        EncoderDevice video1;
        EncoderDevice audio1;
        EncoderDevice video2;
        EncoderDevice audio2;
        EncoderDevice video3;
        EncoderDevice audio3;
        LiveDeviceSource deviceSource;
        LiveDeviceSource deviceSource1;
        LiveDeviceSource deviceSource2;
        LiveDeviceSource deviceSource3;
        PullBroadcastPublishFormat format = null;
        PullBroadcastPublishFormat format1 = null;
        PullBroadcastPublishFormat format2 = null;
        PullBroadcastPublishFormat format3 = null;
        FileArchivePublishFormat fileOut;
        FileArchivePublishFormat fileOut1;
        FileArchivePublishFormat fileOut2;
        FileArchivePublishFormat fileOut3;
        BackgroundWorker bckBroadAndRec;
        private static System.Timers.Timer aTimer;
        ArrayList config;
        bool clickContextual = false;

        private const int CP_NOCLOSE_BUTTON = 0x200;  //junto con protected override CreateParams inhabilitan el boton cerrar de frmProgress
        protected override CreateParams CreateParams
        {
           get
            {
                CreateParams myCp = base.CreateParams;
                myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON;
                return myCp;
            }
        } 

        public frmDVR()
        {
            InitializeComponent();
        }

        private void frmDVR_Load(object sender, EventArgs e)
        {
            config = GetConfig();
            this.Visible = false;
            bckBroadAndRec = new BackgroundWorker();
            bckBroadAndRec.DoWork +=new DoWorkEventHandler(bckBroadAndRec_DoWork);
            bckBroadAndRec.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bckBroadAndRec_RunWorkerCompleted);
            this.MaximizeBox = false;
            btnConfig.Enabled = true;
            GetCamaras();
            aTimer = new System.Timers.Timer(10000);
            aTimer.Elapsed += new ElapsedEventHandler(TimerBroadAndRec);
            aTimer.Enabled = true;

        }

        private void GetCamaras()
        {
            lblCamara.Text = string.Empty;
            lblCamara1.Text = string.Empty;
            lblCamara2.Text = string.Empty;
            lblCamara3.Text = string.Empty;
            job = new LiveJob();
            job1 = new LiveJob();
            job2 = new LiveJob();
            job3 = new LiveJob();

            //camara0
            try
            {
                video = EncoderDevices.FindDevices(EncoderDeviceType.Video)[0];
                try
                {
                    audio = EncoderDevices.FindDevices(EncoderDeviceType.Audio)[0];
                }
                catch
                { }                
                deviceSource = job.AddDeviceSource(video, audio);
                deviceSource.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview, panelVideoPreview.Handle));
                job.ActivateSource(deviceSource);
            }
            catch (Exception)
            {
                job = null;
                lblCamara.Text = "Not device found.";
                panelVideoPreview.BorderStyle = BorderStyle.FixedSingle;
                panelVideoPreview.BackColor = Color.Blue;
                btnCam0.Enabled = false;
            }
            //camara1
            try
            {
                video1 = EncoderDevices.FindDevices(EncoderDeviceType.Video)[1];
                try
                {
                    audio1 = EncoderDevices.FindDevices(EncoderDeviceType.Audio)[1];
                }
                catch
                { }     
                deviceSource1 = job1.AddDeviceSource(video1, audio1);
                deviceSource1.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview1, panelVideoPreview1.Handle));
                job1.ActivateSource(deviceSource1);
            }
            catch (Exception)
            {
                job1 = null;
                lblCamara1.Text = "Not device found.";
                panelVideoPreview1.BorderStyle = BorderStyle.FixedSingle;
                panelVideoPreview1.BackColor = Color.Blue;
                btnCam1.Enabled = false;
            }
            //camara2
            try
            {
                video2 = EncoderDevices.FindDevices(EncoderDeviceType.Video)[2];
                try
                {
                    audio2 = EncoderDevices.FindDevices(EncoderDeviceType.Audio)[2];
                }
                catch
                { }   
                deviceSource2 = job2.AddDeviceSource(video2, audio2);
                deviceSource2.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview2, panelVideoPreview2.Handle));
                job2.ActivateSource(deviceSource2);
            }
            catch (Exception)
            {
                job2 = null;
                lblCamara2.Text = "Not device found.";
                panelVideoPreview2.BorderStyle = BorderStyle.FixedSingle;
                panelVideoPreview2.BackColor = Color.Blue;
                btnCam2.Enabled = false;
            }
            //camara3
            try
            {
                video3 = EncoderDevices.FindDevices(EncoderDeviceType.Video)[3];
                try
                {
                    audio3 = EncoderDevices.FindDevices(EncoderDeviceType.Audio)[3];
                }
                catch
                { }   
                deviceSource3 = job3.AddDeviceSource(video3, audio3);
                deviceSource3.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview3, panelVideoPreview3.Handle));
                job3.ActivateSource(deviceSource3);
            }
            catch (Exception)
            {
                job3 = null;
                lblCamara3.Text = "Not device found.";
                panelVideoPreview3.BorderStyle = BorderStyle.FixedSingle;
                panelVideoPreview3.BackColor = Color.Blue;
                btnCam3.Enabled = false;
            }  
        }

        private void TimerBroadAndRec(object source, ElapsedEventArgs e)
        {
            aTimer.Enabled = false;
            if (job != null)
            {
                job.StopEncoding();
                job.PublishFormats.Remove(fileOut);
                job.PublishFormats.Remove(format);
            }
            if (job1 != null)
            {
                job1.StopEncoding();
                job1.PublishFormats.Remove(fileOut1);
                job1.PublishFormats.Remove(format1);
            }
            if (job2 != null)
            {
                job2.StopEncoding();
                job2.PublishFormats.Remove(fileOut2);
                job2.PublishFormats.Remove(format2);
            }
            if (job3 != null)
            {
                job3.StopEncoding();
                job3.PublishFormats.Remove(fileOut3);
                job3.PublishFormats.Remove(format3);
            }
        /*    string folderRecorder = config[4].ToString();
            System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(folderRecorder);
            IEnumerable<System.IO.FileInfo> fileList = dir.GetFiles("*.*", System.IO.SearchOption.AllDirectories);
            while (EspacioEnDisco() < 65)
            {
                System.IO.FileInfo olderFile = (from file in fileList
                                                let len = GetFileDateTime(file)
                                                where len > DateTime.Parse("2000-01-01")
                                                orderby len ascending
                                                select file).First();
                File.Delete(olderFile.FullName);

            }*/





            bckBroadAndRec.RunWorkerAsync();
        }

        private void bckBroadAndRec_DoWork(object sender, DoWorkEventArgs e)
        {
            string recordingPath = config[4].ToString(); //en el indice 4 está el path para grabar
            if (!File.Exists(recordingPath))
            {
                try
                {
                    System.IO.Directory.CreateDirectory(recordingPath);
                    if (!File.Exists(recordingPath + @"\Camara1")) System.IO.Directory.CreateDirectory(recordingPath + @"\Camara1");
                    if (!File.Exists(recordingPath + @"\Camara2")) System.IO.Directory.CreateDirectory(recordingPath + @"\Camara2");
                    if (!File.Exists(recordingPath + @"\Camara3")) System.IO.Directory.CreateDirectory(recordingPath + @"\Camara3");
                    if (!File.Exists(recordingPath + @"\Camara4")) System.IO.Directory.CreateDirectory(recordingPath + @"\Camara4");
                }
                catch (Exception)
                {
                    MessageBox.Show("La carpeta elegida para grabar las cámaras no es válida", "Trend DVR", 
                                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            if (video != null && job != null)
            {    
             //   job.ApplyPreset(LivePresets.VC1256kDSL16x9);
                format = new PullBroadcastPublishFormat();
                format.BroadcastPort = 8080;
                format.MaximumNumberOfConnections = 2;
                job.PublishFormats.Add(format);
                if (config[0].ToString() == "1") //está configurada en config.log para que grabe
                {
                    fileOut = new FileArchivePublishFormat();
                    fileOut.OutputFileName = String.Format(recordingPath + @"\Camara1\camara1_{0:yyyy-MM-dd_hhmmss}.wmv", DateTime.Now);
                    job.PublishFormats.Add(fileOut);
                }
                job.StartEncoding();
            }
            if (video1 != null && job1 != null)
            {
             //   job1.ApplyPreset(LivePresets.VC1256kDSL16x9);
                format1 = new PullBroadcastPublishFormat();
                format1.BroadcastPort = 8081;
                format1.MaximumNumberOfConnections = 2;
                job1.PublishFormats.Add(format1);
                if (config[1].ToString() == "1") //está configurada en config.log para que grabe
                {
                    fileOut1 = new FileArchivePublishFormat();
                    fileOut1.OutputFileName = String.Format(recordingPath + @"\Camara2\camara2_{0:yyyy-MM-dd_hhmmss}.wmv", DateTime.Now);
                    job1.PublishFormats.Add(fileOut1);
                }
                job1.StartEncoding();
            }
            if (video2 != null && job2 != null)
            {
           //     job2.ApplyPreset(LivePresets.VC1256kDSL16x9);
                format2 = new PullBroadcastPublishFormat();
                format2.BroadcastPort = 8082;
                format2.MaximumNumberOfConnections = 2;
                job2.PublishFormats.Add(format2);
                if (config[2].ToString() == "1") //está configurada en config.log para que grabe
                {
                    fileOut2 = new FileArchivePublishFormat();
                    fileOut2.OutputFileName = String.Format(recordingPath + @"\Camara3\camara3_{0:yyyy-MM-dd_hhmmss}.wmv", DateTime.Now);
                    job2.PublishFormats.Add(fileOut2);
                }
                job2.StartEncoding();
            }
            if (video3 != null && job3 != null)
            {
            //    job3.ApplyPreset(LivePresets.VC1256kDSL16x9);
                format3 = new PullBroadcastPublishFormat();
                format3.BroadcastPort = 8083;
                format3.MaximumNumberOfConnections = 2;
                job3.PublishFormats.Add(format3);
                if (config[3].ToString() == "1") //está configurada en config.log para que grabe
                {
                    fileOut3 = new FileArchivePublishFormat();
                    fileOut3.OutputFileName = String.Format(recordingPath + @"\Camara4\camara4_{0:yyyy-MM-dd_hhmmss}.wmv", DateTime.Now);
                    job3.PublishFormats.Add(fileOut3);
                }
                job3.StartEncoding();
            }
        }

        private void bckBroadAndRec_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            aTimer.Enabled = true;
            aTimer.Interval = 600000;
        }

        private void btnCam0_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            panelVideoPreview.BringToFront();
            panelVideoPreview.Size = new Size(640, 480);
            deviceSource.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview, panelVideoPreview.Handle));
            Cursor.Current = Cursors.Arrow;
        }

        private void btnCam1_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            panelVideoPreview1.BringToFront();
            panelVideoPreview1.Size = new Size(640, 480);
            panelVideoPreview1.Location = new Point(10, 10);
            deviceSource1.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview1, panelVideoPreview1.Handle));
            Cursor.Current = Cursors.Arrow;
        }

        private void btnCam2_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            panelVideoPreview2.BringToFront();
            panelVideoPreview2.Size = new Size(640, 480);
            panelVideoPreview2.Location = new Point(10, 10);
            deviceSource2.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview2, panelVideoPreview2.Handle));
            Cursor.Current = Cursors.Arrow;
        }

        private void btnCam3_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            panelVideoPreview3.BringToFront();
            panelVideoPreview3.Size = new Size(640, 480);
            panelVideoPreview3.Location = new Point(10, 10);
            deviceSource3.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview3, panelVideoPreview3.Handle));
            Cursor.Current = Cursors.Arrow;
        }

        private void btnTodas_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            //camara 0
            if(panelVideoPreview.Width > 315)
            {
                panelVideoPreview.Size = new Size(315, 235);
                deviceSource.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview, panelVideoPreview.Handle));            
            }
            //camara 1
            if (panelVideoPreview1.Location.X == 10 && panelVideoPreview1.Location.Y == 10)
            {
                panelVideoPreview1.Size = new Size(315, 235);
                panelVideoPreview1.Location = new Point(335, 10);
                deviceSource1.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview1, panelVideoPreview1.Handle));
            }
            //camara 2
            if (panelVideoPreview2.Location.X == 10 && panelVideoPreview2.Location.Y == 10)
            {
                panelVideoPreview2.Size = new Size(315, 235);
                panelVideoPreview2.Location = new Point(10, 255);
                deviceSource2.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview2, panelVideoPreview2.Handle));
            }
            //camara 3
            if (panelVideoPreview3.Location.X == 10 && panelVideoPreview3.Location.Y == 10)
            {
                panelVideoPreview3.Size = new Size(315, 235);
                panelVideoPreview3.Location = new Point(335, 255);
                deviceSource3.PreviewWindow = new PreviewWindow(new HandleRef(panelVideoPreview3, panelVideoPreview3.Handle));
            }

            Cursor.Current = Cursors.Arrow;            
        }

        private void btnConfig_Click(object sender, EventArgs e)
        {
         //   Process.Start(@"N:\NcSoftware\01_C_sharp\DVR WebCam\DVR WebCam\config\bin\Debug\config.exe");
            Process.Start(Application.StartupPath + @"\config.exe");
        }

        private void frmConfig_FormClosed(object sender, FormClosedEventArgs e)
        {

        }

        private void frmDVR_FormClosing(object sender, FormClosingEventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            StopJob();
            Cursor.Current = Cursors.Arrow;
        }

        void StopJob()
        {
            if (job != null)
            {
                job.StopEncoding();
                job.RemoveDeviceSource(deviceSource);
                deviceSource.PreviewWindow = null;
                deviceSource = null;
            }
            if (job1 != null)
            {
                job1.StopEncoding();
                job1.RemoveDeviceSource(deviceSource1);
                deviceSource1.PreviewWindow = null;
                deviceSource1 = null;
            }
            if (job2 != null)
            {
                job2.StopEncoding();
                job2.RemoveDeviceSource(deviceSource2);
                deviceSource2.PreviewWindow = null;
                deviceSource2 = null;
            }
            if (job3 != null)
            {
                job3.StopEncoding();
                job3.RemoveDeviceSource(deviceSource3);
                deviceSource3.PreviewWindow = null;
                deviceSource3 = null;
            }
        }

        private ArrayList GetConfig()
        {
            ArrayList camara = new ArrayList();
            string path = Application.StartupPath;
            string line;
            System.IO.StreamReader file = new System.IO.StreamReader(path + @"\config.log");
            while ((line = file.ReadLine()) != null)
            {
                camara.Add(line);
            }
            file.Close();
            return camara;
        }

        private long EspacioEnDisco()
        {
            string folderRecorder = config[4].ToString();
            string driveRecorder = folderRecorder.Substring(0, 1);
            DriveInfo drive = new DriveInfo(driveRecorder);
            long space = drive.AvailableFreeSpace; // devuelve bytes
            space = space / 1024; // kilobytes
            space = space / 1024; // megabytes
            space = space / 1024; // gigabytes
            return space;
        }

        static DateTime GetFileDateTime(System.IO.FileInfo fi)
        {
            DateTime fecha;
            fecha = fi.CreationTime;
            return fecha;
        }

        private void frmDVR_Activated(object sender, EventArgs e)
        {
            if (clickContextual) this.Visible = true;
            else this.Visible = false;
        }

        private void mnuMostrarApp_Click(object sender, EventArgs e)
        {
            clickContextual = true;
            Show();
            WindowState = FormWindowState.Normal;
            Activate();
        }

        private void frmDVR_Deactivate(object sender, EventArgs e)
        {
            this.Visible = false;
        }



    }
}
